home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / comms / areacod4.zip / AREA.C next >
Text File  |  1995-02-08  |  22KB  |  758 lines

  1. /* area:  Areacode Finder v1.4
  2.  
  3.   Program searches for telephone area codes/state information by
  4.   area code, state name, city name, or postal codes.
  5.  
  6.   Author:  Jason Mathews <mathews@nssdc.gsfc.nasa.gov>
  7.        NASA/Goddard Space Flight Center - Code 633.2
  8.        Greenbelt Road
  9.        Greenbelt, MD 20771-0001  USA
  10.  
  11.   Please notify me at the address above if there are any missing area codes
  12.   or errors found in this program.  I would appreciate any comments if you
  13.   find this program useful or would like to see more features.
  14.  
  15.   Copyright (C) 1992-95 by Jason Mathews.  Permission is granted to any
  16.   individual or institution to use, copy or redistribute this software so long
  17.   as it is not sold for profit, provided this copyright notice is retained.
  18.  
  19.   Usage: area                   - help
  20.      area *                 - list all area codes
  21.      area XXX [XXX...]      - find match
  22.       where XXX is an area code, state, city, or postal code.
  23.  
  24.     States and cities are found by wildcard match if wildcard characters
  25.     ('*' and/or '?') are specified, otherwise a substring comparison
  26.     is made.  All comparisons are case insensitive; e.g., "NEW" and "New"
  27.     are equivalent.
  28.  
  29.     - Two letter state/postal codes like TX for Texas, CA for California
  30.       can be used, otherwise type in the state name.
  31.     - Enter two word state names like "New*Jersey" or "New York".
  32.     - Enter three digit area code to find a state such as 301 for Maryland.
  33.     - Enter city names in between quotes like "Los Angeles"
  34.       or substrings such as "cisco" for "San Francisco".
  35.     - Enter "*" for a list of all Area Codes.
  36.  
  37.   Compilers: This program will compile and link with Turbo C 2.0, UNIX gcc,
  38.          VAX/VMS C, and other ANSI compilers.
  39.  
  40.     tcc -Z -O -d area.c    (MS-DOS)
  41.     gcc -O area.c -o area   (unix)
  42.  
  43.   History:
  44.  
  45.   V1.0 26-Nov-92  - Original version for MS-DOS/UNIX.
  46.  
  47.   V1.1 20-Apr-94  - Optimized postal code search.
  48.           - Added 210, 407, 508, 516, 610, 708, 810, 903, 908,
  49.             909, 910, and 917 area codes (effective 1/94).
  50.           - Updated 706 and 905 area codes.
  51.           - Added Canada, Bahamas (BA), Bermuda (BM) postal codes.
  52.  
  53.   V1.2 24-May-94  - Fixed several database corrections.
  54.           - Added city search as suggested by Peter Mauzey.
  55.           - Added strstr function for some "non-ANSI" compilers.
  56.  
  57.   V1.3 1-Jun-94   - Combined city and state search for faster searches.
  58.           - Improved search with wildcard expression or substring
  59.           - search depending on the target string.
  60.           - Fixed wildcard evaluation with "*?" expression.
  61.           - Added JM, NT postal codes + more cities.
  62.  
  63.   V1.4 8-Feb-95   - Added 630 area code and updated Illinois info.
  64.  
  65.  *************************************************************************/
  66.  
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <ctype.h>
  71.  
  72. #define N_ZONES  71
  73. #define N_CODES 177
  74.  
  75. #ifdef __TURBOC__
  76.  
  77. # define ToLower(c) tolower(c)
  78. # define ToUpper(c) toupper(c)
  79.  
  80. #else /* ?unix */
  81.  
  82. /* Avoid using const if compiler does not support it */
  83. # ifndef __STDC__
  84. #   define const
  85. # endif
  86.  
  87. /*  some compilers don't check if a character is already upper or lower
  88.  *  case in the toupper/tolower functions, so we define our own here.
  89.  */
  90.  
  91. # ifndef _tolower
  92. #   define _tolower(c) ((c) + 'a' - 'A')
  93. # endif
  94.  
  95. # ifndef _toupper
  96. #   define _toupper(c) ((c) + 'A' - 'a')
  97. # endif
  98.  
  99. # define ToLower(c) (isupper(c) ? _tolower(c) : (c))
  100. # define ToUpper(c) (islower(c) ? _toupper(c) : (c))
  101.  
  102. #endif /* ?__TURBOC__ */
  103.  
  104. #ifdef VMS
  105. #  define EXIT exit
  106. #else
  107. #  define EXIT return
  108. #endif /* VMS */
  109.  
  110.  
  111. /* Global variables */
  112.  
  113. const char copyright[] =
  114.     "   ** Area Code Finder v1.4 **    (C) Jason Mathews 1992-95\n";
  115.  
  116. int zone = -1;  /* zone code */
  117.  
  118. typedef struct zone_s {
  119.     char *code;
  120.     char *stateName;
  121. } zone_t;
  122.  
  123. zone_t areazones[N_ZONES] = {
  124. "AL","Alabama",
  125. "AK","Alaska",
  126. "AZ","Arizona",
  127. "AR","Arkansas",
  128. "BC","British Columbia",
  129. "CA","California",
  130. "CN","Canada",
  131. "CO","Colorado",
  132. "CT","Connecticut",
  133. "DE","Delaware",
  134. "DC","Washington, District of Columbia",
  135. "FL","Florida",
  136. "GA","Georgia",
  137. "HI","Hawaii",
  138. "ID","Idaho",
  139. "IL","Illinois",
  140. "IN","Indiana",
  141. "IA","Iowa",
  142. "KS","Kansas",
  143. "KY","Kentucky",
  144. "LA","Louisiana",
  145. "ME","Maine",
  146. "MD","Maryland",
  147. "MA","Massachusetts",
  148. "MI","Michigan",
  149. "MN","Minnesota",
  150. "MS","Mississippi",
  151. "MO","Missouri",
  152. "MT","Montana",
  153. "NE","Nebraska",
  154. "NV","Nevada",
  155. "NH","New Hampshire",
  156. "NJ","New Jersey",
  157. "NM","New Mexico",
  158. "NY","New York",
  159. "NC","North Carolina",
  160. "ND","North Dakota",
  161. "OH","Ohio",
  162. "OK","Oklahoma",
  163. "OR","Oregon",
  164. "PA","Pennsylvania",
  165. "PR","Puerto Rico",
  166. "RI","Rhode Island",
  167. "SC","South Carolina",
  168. "SD","South Dakota",
  169. "TN","Tennessee",
  170. "TX","Texas",
  171. "UT","Utah",
  172. "VT","Vermont",
  173. "VI","Virgin Islands",
  174. "VA","Virginia",
  175. "WA","Washington",
  176. "WV","West Virginia",
  177. "WI","Wisconsin",
  178. "WY","Wyoming",
  179. "  ","Wide area (tollfree)",
  180. "  ","International Access",
  181. "BA","Bahamas",
  182. "BM","Bermuda",
  183. "JM","Jamaica",
  184. "AB","Alberta",
  185. "MB","Manitoba",
  186. "NB","New Brunswick",
  187. "NF","Newfoundland",
  188. "NS","Nova Scotia",
  189. "NT","N.W. Territory",
  190. "ON","Ontario",
  191. "PE","Prince Edward Island",
  192. "PO","Quebec",
  193. "SK","Saskatchewan",
  194. "YT","Yukon Territory"
  195. };
  196.  
  197. typedef struct code_s {
  198.     short zcode;        /* index into zonelist (0..n) */
  199.  
  200.     short areaCode;     /* local area code.
  201.              * if areacode is -1 then the list continues from
  202.              * the previous entry.
  203.              */
  204.  
  205.     char *list;         /* list of cities, counties, ... with same areacode.
  206.              * if list is NULL (0) then this area code covers
  207.              * the entire area.
  208.              */
  209. } code_t;
  210.  
  211. code_t areacodes[N_CODES+1] = {
  212. 0,205,0,
  213. 1,907,0,
  214. 2,602,0,
  215. 3,501,0,
  216. 4,604,0, /* British Columbia */
  217.  
  218. /* CALIFORNIA */
  219. 5,209,"Fresno and Stockton",
  220. 5,213,"Los Angeles",
  221. 5,310,"Beverly Hills, Long Beach, Whittier",
  222. 5,408,"San Jose, Sunnyvale",
  223. 5,415,"San Francisco area",
  224. 5,510,"Oakland, Berkeley, San Francisco",
  225. 5,619,"Palm Springs, San Diego and the Imperial Valley",
  226. 5,707,"Eureka, Napa, Santa Rosa",
  227. 5,714,"Anaheim, Orange County",
  228. 5,805,"Bakersfield, Ventura, Simi Valley",
  229. 5,818,"Burbank, Pasadena, Van Nuys",
  230. 5,909,"Riverside; Southwestern CA",
  231. 5,916,"Sacramento and South Lake Tahoe",
  232.  
  233. /* CANADA */
  234. 6,604,"British Columbia",
  235. 6,403,"Alberta and Yukon",
  236. 6,306,"Saskatchewan",
  237. 6,204,"Manitoba",
  238. 6,416,"Toronto, Ont.",
  239. 6,519,"London, Ont.",
  240. 6,613,"Ottawa, Ont.",
  241. 6,705,"East Ontario",
  242. 6,807,"West Ontario",
  243. 6,905,"Southern Ontario",
  244. 6,418,"Northern Quebec",
  245. 6,514,"Montreal, Quebec",
  246. 6,819,"NW Quebec",
  247. 6,709,"Newfoundland",
  248. 6,506,"New Brunswick",
  249. 6,902,"Nova Scotia, Prince Edward Island",
  250.  
  251. 7,303,"Boulder, Denver, Grand Junction",
  252. 7,719,"Colorado Springs, Pueblo",
  253. 8,203,0,
  254. 9,302,0,
  255. 10,202,0,
  256.  
  257. /* Florida */
  258. 11,305,"Miami, Key West, Ft. Lauderdale",
  259. 11,407,"Orlando, West Palm Beach",
  260. 11,813,"Ft. Myers, Tampa, Winter Haven",
  261. 11,904,"Jacksonville, Tallahassee",
  262.  
  263. 12,404,"Atlanta, Rome",
  264. 12,706,"Athens, Augusta, Columbus",
  265. 12,912,"Macon, Savannah, Waycross",
  266. 13,808,0,
  267. 14,208,0,
  268.  
  269. /* Illinois */
  270. 15,217,"Champaign-Urbana, Decatur, Springfield",
  271. 15,309,"Galesburg, Macomb, Peoria",
  272. 15,312,"Chicago, O'hare Airport",
  273. 15,618,"Alton, Carbondale, Centralia, Mount Vernon",
  274. 15,630, "Wireless Devices in Chicago (312) and suburbs (708)",
  275. 15,708,"Aurora, Elgin, Plano, Waukegan",
  276. 15,815,"De Kalb, Joliet, Moline, Ottawa, Rockford",
  277.  
  278. 16,812,"Evansville",
  279. 16,219,"Gary, South Bend, Warsaw",
  280. 16,317,"Indianapolis, Kokomo",
  281.  
  282. 17,712,"Council Bluffs, Sioux City",
  283. 17,515,"Des Moines",
  284. 17,319,"Dubuque",
  285.  
  286. 18,316,"Dodge City, Emporia, Wichita",
  287. 18,913,"Hays, Kansas City, Overland Park, Topeka",
  288.  
  289. 19,502,"Louisville, Frankfort, Paducah, Shelbyville",
  290. 19,606,"Ashland, Lexington, Middlesboro, Winchester",
  291.  
  292. 20,504,"Baton Rouge, New Orleans",
  293. 20,318,"Lake Charles, Monroe, Shreveport",
  294. 21,207,0,
  295.  
  296. /* Maryland */
  297. 22,301,"Bethesda, Cumberland, Frederick, Greenbelt,",
  298. 22,-1,"Hagerstown, Rockville, Silver Spring",
  299. 22,410,"Annapolis, Baltimore, Ellicott City, Salisbury",
  300.  
  301. 23,413,"Pittsfield, Springfield",
  302. 23,508,"Fall River, Framingham, New Bedford, Worchester",
  303. 23,617,"Boston, Cambridge, Plymouth",
  304. 24,313,"Detroit, Ann Arbor",
  305. 24,616,"Battle Creek, Grand Rapids, Kalamazoo",
  306. 24,517,"Jackson, Lansing",
  307. 24,810,"Flint",
  308. 24,906,"Escanaba, Sault Ste. Marie",
  309. 25,218,"Duluth",
  310. 25,612,"Minneapolis, St. Paul",
  311. 25,507,"Mankato, Rochester",
  312. 26,601,0,
  313. 27,816,"Belton, Independence, Kansas City, Marshall, St. Joseph, Sedalia",
  314. 27,314,"St. Louis, Cape Girardeau, Columbia, Fulton, Hannibal,",
  315. 27,-1,"Jefferson City, Mexico, Poplar Bluff, Rolla",
  316. 27,417,"Joplin, Springfield",
  317. 28,406,0,
  318. 29,402,"Omaha, Lincoln",
  319. 29,308,"North Platte, Scottsbluff",
  320. 30,702,0,
  321. 31,603,0,
  322. 32,201,"Newark, Hackensack, Jersey City, Patterson",
  323. 32,609,"Atlantic City, Camden, Trenton, Wildwood",
  324. 32,908,"Elizabeth, New Brunswick",
  325. 33,505,0,
  326. 34,518,"Albany, Schenectady",
  327. 34,607,"Binghamton, Corning",
  328. 34,716,"Buffalo, Niagara Falls, Rochester",
  329. 34,516,"Hempstead, Long Island area",
  330. 34,914,"Mount Vernon, White Plains",
  331. 34,212,"New York City (Manhattan and Bronx)",
  332. 34,718,"New York City (Queens, Brooklyn and Staten Island)",
  333. 34,917,"New York City (All Locations)",
  334. 34,315,"Syracuse, Watertown",
  335. 35,704,"Asheville, Charlotte, Salisbury",
  336. 35,910,"Greensboro, Winston-Salem",
  337. 35,919,"Raleigh",
  338. 36,701,0,
  339. 37,216,"Akron, Canton, Cleveland, Youngstown",
  340. 37,513,"Cincinnati, Dayton, Springfield",
  341. 37,614,"Columbus, Marion, Zanesville",
  342. 37,419,"Lima, Toledo",
  343. 38,918,"Bartlesville, McAlester, Muskogee, Tulsa",
  344. 38,405,"Enid, Oklahoma City, Norman, Ponca City, Stillwater",
  345. 39,503,0,
  346. 40,215,"Levittown, Philadelphia, Quakertown",
  347. 40,412,"Butler, Indiana, New Castle, Pittsburgh, Uniontown",
  348. 40,610,"Allentown, Bethlehem, Reading, Swarthmore, Valleyforge",
  349. 40,717,"Gettysburg, Harrisburg, Hershey, Lancaster, Scranton",
  350. 40,814,"Bradford, Clarion, Erie, Punxsutawney, Williamsburg",
  351. 41,809,"Anguilla, Antigua, Bahamas, Barbados, Bequia, Bermuda, Cayman Islands,",
  352. 41,-1,"Dominica, Dominican Republic, Grenada, Jamaica, Montserrat, Mustique,",
  353. 41,-1,"Nevis, Palm Island, Puerto Rico, St. Kitts, St. Lucia, St. Vincent,",
  354. 41,-1,"Trinidad and Tobago, Turks and Caicos, Union Island, Virgin Islands",
  355. 42,401,0,
  356. 43,803,0,
  357. 44,605,0,
  358. 45,615,"Chattanooga, Johnson City, Knoxville, Nashville",
  359. 45,901,"Jackson, Memphis",
  360.  
  361. /* Texas */
  362. 46,210,"San Antonio",
  363. 46,214,"Dallas, Ennis, Greenville, Jefferson, Longview, Sherman",
  364. 46,409,"Bay City, Beaumont, Bryan, College Station, Galveston, Huntsville",
  365. 46,512,"Austin, Brownsville, Corpus Christi, Del Rio, Eagle Pass,",
  366. 46,-1,"Laredo, McAllen, Victoria",
  367. 46,713,"Houston, Baytown, Pasadena",
  368. 46,806,"Amarillo, Dalhart, Lubbock",
  369. 46,817,"Fort Worth, Denton, Temple, Waco, Wichita Falls",
  370. 46,903,"Texarkana, Tyler",
  371. 46,915,"Abilene, Alpine, Big Spring, El Paso, Midland, Odessa",
  372.  
  373. 47,801,0,
  374. 48,802,0,
  375. 49,809,0,
  376. 50,804,"Charlottesville, Lynchburg, Newport News,",
  377. 50,-1,"Norfolk, Portsmouth, Richmond, Williamsburg",
  378. 50,703,"Alexandria, Arlington, Fairfax, Fredricksburg,",
  379. 50,-1,"Roanoke, Staunton, Vienna, Winchester",
  380. 51,206,"Seattle, Olympia, Tacoma, Vancouver",
  381. 51,509,"Spokane, Walla Walla, Yakima",
  382. 52,304,0,
  383. 53,414,"Appleton, Milwaukee, Green Bay, Racine",
  384. 53,608,"Beloit, La Crosse, Madison",
  385. 53,715,"Eau Claire, Wausau",
  386. 54,307,0,
  387. 55,800,0,
  388.  
  389. 56,11,0,  /* International */
  390. 57,809,0, /* Bahamas */
  391. 58,809,0, /* Bermuda */
  392. 59,809,0, /* Jamaica */
  393.  
  394. /* CANADA */
  395.  
  396. 60,403,0, /* Alberta */
  397. 61,204,0, /* Manitoba */
  398. 62,506,0, /* New Brunswick */
  399. 63,709,0, /* Newfoundland */
  400. 64,902,0, /* Nova Scotia */
  401. 65,604,0, /* NW Territory */
  402. 66,416,"Toronto", /* Ontario */
  403. 66,519,"London",
  404. 66,613,"Ottawa",
  405. 66,705,"North Bay",
  406. 66,807,"Fort William, Thunder Bay",
  407. 66,905,"Southern Ontario",
  408. 67,902,0, /* Prince Edward */
  409. 68,418,"Quebec City",
  410. 68,514,"Montreal",
  411. 68,819,"Sherbrooke",
  412. 69,306,0, /* Saskatchewan */
  413. 70,403,0, /* Yukon Territory */
  414.  
  415. 99,0,0    /* sentinel entry */
  416. };
  417.  
  418. #ifndef __TURBOC__
  419. /*---------------------------------------------------------------------*
  420.  * strlwr - converts a string to lower-case
  421.  *
  422.  * Returns: pointer to the converted string
  423.  *---------------------------------------------------------------------*/
  424. char* strlwr( char* s )
  425. {
  426.   if (s != 0)
  427.   {
  428.       register char *ps = s;
  429.       while (*ps)
  430.       {
  431.       if (isupper((unsigned char)*ps))
  432.         *ps = _tolower((unsigned char)*ps);
  433.       ps++;
  434.     }
  435.     }
  436.   return s;
  437. }
  438. #endif /* ?!__TURBOC__ */
  439.  
  440. /*-----------------------------------------------------------------------*
  441.  * stristr - Scans a string for the occurrence of a given string
  442.  *           ignoring case
  443.  *
  444.  * Returns:  1 if str1 contains str2, otherwise 0.
  445.  *-----------------------------------------------------------------------*/
  446. int stristr( const char *str1, const char *str2 )
  447. {
  448.   register const char *s1, *s2;
  449.   char c1, c2;
  450.  
  451.   if (!*str2) return 1;           /* return 1 if str2 empty */
  452.  
  453.   do
  454.   {
  455.     s1 = str1; c1 = *s1;
  456.     s2 = str2; c2 = *s2;
  457.     while (c1 && c2)
  458.     {
  459.     if (isupper(c1)) c1 = _tolower(c1);
  460.     if (isupper(c2)) c2 = _tolower(c2);
  461.     if (c1==c2)    /* str1[i] == str2[i] ? */
  462.     {
  463.         c1 = *(++s1);  c2 = *(++s2);
  464.     }
  465.     else break;
  466.      }
  467.      if (!*s2) return 1;    /* target parsed - match found */
  468.      ++str1;    /* try next position of str1 */
  469.   } while (*str1);
  470.   return 0;
  471. }
  472.  
  473. /*-----------------------------------------------------------------------*
  474.  * hasWildCard: Checks if wildcard characters are present in string s
  475.  *
  476.  * Returns:     1 if '*' or '?' are found, 0 otherwise.
  477.  *-----------------------------------------------------------------------*/
  478. int hasWildCard( const char *s )
  479. {
  480.     while (*s)
  481.     {
  482.     if (*s == '*' || *s == '?') return 1;
  483.     s++;
  484.     }
  485.     return 0;
  486. }
  487.  
  488. /*-----------------------------------------------------------------------*
  489.  * match:       match string s with wildcard pattern
  490.  *
  491.  * Returns:     1 if the pattern matches the string
  492.  *              0 otherwise.
  493.  *-----------------------------------------------------------------------*/
  494. int match (const char *target, const char *pattern)
  495. {
  496.     register char symbol;
  497.     register const char *s = target;
  498.     const char *old_pat = 0;  /* address of last wildcard pattern */
  499.     const char *old_target;   /* address of target string */
  500.  
  501.   /*  Parse each string character by character until
  502.    *  a mismatch is found or the end of one is reached.
  503.    */
  504.  matchRetry:
  505.     while (*pattern != 0)
  506.     {
  507.     switch (*pattern) {
  508.        case '?':
  509.         goto matchNext; /* match any symbol, except NULL */
  510.  
  511.        case '*':
  512.         old_pat = pattern++;
  513.         while (*pattern != 0)
  514.         {
  515.           switch (*pattern) {
  516.            case '?':
  517.             if (!*s) return 0; /* no match? */
  518.             s++;  pattern++;
  519.             continue;
  520.            case '*': /* handle multiple *'s */
  521.             pattern++;
  522.             continue;
  523.           } /* switch */
  524.           break;
  525.         } /* while */
  526.         /*  If the end of the expression was parsed
  527.          *  and the last character was a wildcard (*) then
  528.          *  the rest of the string is accepted.
  529.          */
  530.         if (!*pattern) return 1;
  531.         for (symbol = ToLower(*pattern);; s++)
  532.         {
  533.             if (!*s) return 0; /* no match */
  534.             if (ToLower(*s) == symbol)
  535.             {
  536.             old_target = s + 1;
  537.             break;
  538.             }
  539.         }
  540.     goto matchNext2;
  541.  
  542.        default:
  543.         symbol = ToLower(*pattern);
  544.     } /* switch */
  545.  
  546.     if (ToLower(*s) != symbol) break; /* mismatch? */
  547.  
  548.   matchNext:
  549.     if (!*s) break;
  550.   matchNext2:
  551.     s++;  pattern++;   /* increment strings */
  552.     symbol = ToLower(*pattern);
  553.     } /* while */
  554.  
  555.     /* check if match failed */
  556.     if (ToLower(*s) != symbol && old_pat && *old_target != 0)
  557.     {
  558.     /*  check if a wildcard was previously parsed, if so back up
  559.      *  to that pattern and try again.
  560.      */
  561.     pattern = old_pat; /* reset pattern */
  562.     s = old_target++;  /* reset target to last position */
  563.     goto matchRetry;
  564.     }
  565.  
  566.   /*    Check if the last two characters match:
  567.    *    either strings must be NULL to end the loop,
  568.    *    so they both must equal NULL for a match.
  569.    */
  570.     return (*pattern == *s);
  571. }
  572.  
  573. /*-----------------------------------------------------------------------*
  574.  * Printcode:   Print the entry for the specified areacode
  575.  *
  576.  *              Keep track of the previous zone and
  577.  *              only print the state information when this changes.
  578.  *-----------------------------------------------------------------------*/
  579. void PrintCode (int code)
  580. {
  581.     int newzone = areacodes[code].zcode;
  582.  
  583.     /*  check if entry is continued from the previous one
  584.      *  (identified by the -1 areacode) and already printed.
  585.      */
  586.     if (areacodes[code].areaCode < 0) return;
  587.     if (newzone != zone)
  588.     {
  589.     zone = newzone;
  590.     printf("\n%s  %s area code(s):\n",
  591.         areazones[zone].code,
  592.         areazones[zone].stateName);
  593.     }
  594.     printf("    %03d %s\n", areacodes[code].areaCode,
  595.     areacodes[code].list ? areacodes[code].list : "All locations.");
  596.  
  597.     /* Check if areacode list continues on next entry */
  598.     while (areacodes[++code].areaCode == -1)
  599.     printf("        %s\n", areacodes[code].list);
  600. }
  601.  
  602. /*-----------------------------------------------------------------------*
  603.  * FindAbbrev:  Find postal code in list of states matching the string s
  604.  *
  605.  * returns:     1 if match found.
  606.  *              0 otherwise.
  607.  *-----------------------------------------------------------------------*/
  608. int FindAbbrev (const char *s)
  609. {
  610.     int  i;
  611.     char ch1, ch2;      /* target characters in uppercase */
  612.     ch1 = ToUpper(*s);
  613.     ch2 = ToUpper(*(s+1));
  614.     for (i=0; i < N_ZONES; i++)
  615.     {
  616.     if (ch1==areazones[i].code[0] && ch2==areazones[i].code[1])
  617.     {
  618.         int code = 0;
  619.         /*  Locate areacode in list and
  620.          *  print all entries for that state.
  621.          */
  622.         while (areacodes[code].zcode < i) code++;
  623.         while (areacodes[code].zcode==i)
  624.         {
  625.             PrintCode(code++);
  626.         }
  627.         return 1;
  628.     }
  629.     }
  630.     return 0;
  631. }
  632.  
  633. /*-----------------------------------------------------------------------*
  634.  * FindCode:    Find areacode in list
  635.  *
  636.  * returns:     1 if areacode is found.
  637.  *              0 otherwise.
  638.  *-----------------------------------------------------------------------*/
  639. int FindCode (const char *s)
  640. {
  641.     int i;
  642.     int code = atoi(s);
  643.     if (code == 0) return 0; /* invalid code */
  644.  
  645.     for (i=0; i < N_CODES; i++)
  646.     {
  647.     if (areacodes[i].areaCode == code)
  648.     {
  649.         PrintCode(i);
  650.         return 1;
  651.     }
  652.     }
  653.     return 0;
  654. }
  655.  
  656. /*-----------------------------------------------------------------------*
  657.  * FindString:  Find all states and/or cities matching the pattern s
  658.  *
  659.  * Returns:     1 if string is found.
  660.  *              0 otherwise.
  661.  *-----------------------------------------------------------------------*/
  662. int FindString (const char *s)
  663. {
  664.     int i;
  665.     int rc = 0;  /* return code */
  666.     int code, pos;
  667.     char target[30];
  668.     int wildcards = hasWildCard(s);
  669.     int (*cmp)(const char*, const char*) = wildcards ? match : stristr;
  670.  
  671.     if (*s == '*' && !*(s+1))   /* show all codes and return */
  672.     {
  673.     for (code=0; code < N_CODES; code++)
  674.         PrintCode(code);
  675.     return 1;
  676.     }
  677.  
  678.     strncpy(target, s, sizeof(target)); /* copy target string */
  679.     strlwr(target);                     /* convert to lower case */
  680.  
  681.     for (code=0, i=0; i < N_ZONES; i++)
  682.     {
  683.     if (cmp(areazones[i].stateName, target))
  684.     {
  685.         /* print all codes for found zone */
  686.         while (areacodes[code].zcode==i)
  687.         {
  688.         PrintCode(code++);
  689.         }
  690.         rc = 1;
  691.     }
  692.     else /* try city search */
  693.     {
  694.         while (areacodes[code].list != 0 && areacodes[code].zcode == i)
  695.         {
  696.         if (cmp(areacodes[code].list, target))
  697.         {
  698.             pos = code;
  699.             while (areacodes[pos].areaCode < 0) pos--;
  700.             PrintCode(pos);
  701.             rc = 1;
  702.         }
  703.         code++;
  704.         }
  705.         /* set zone position */
  706.         while (areacodes[code].zcode <= i) code++;
  707.     }
  708.     } /* for */
  709.     return rc;
  710. }
  711.  
  712.  
  713. int main (int argc, char **argv)
  714. {
  715.     int i;
  716.  
  717.     printf(copyright);
  718.     if (argc==1)
  719.     {
  720.     printf("\nProgram searches for telephone area codes,\n");
  721.     printf("   as area xxx xxx xxx etc.\n");
  722.     printf("   xxx is an Area Code, State name, or City.\n\n");
  723.     printf("   Two letter state/postal codes like TX for Texas, CA for California\n");
  724.     printf("      can be used, otherwise type in the state or city name.\n");
  725.     printf("   Enter wildcard expressions such as: New* or *Green?b*\n");
  726.     printf("   Enter substrings like: cisco or east\n");
  727.     printf("   Enter multiple words in between quotes like: \"Los Angeles\" or \"New York\"\n");
  728.     printf("   Enter area * for a list of all Area Codes.\n");
  729.     EXIT(0);
  730.     }
  731.  
  732.     for (i=1; i < argc; i++)
  733.     {
  734.     zone = -1;      /* reset zone number */
  735.     if (hasWildCard(argv[i])) goto others;
  736.     switch (strlen(argv[i])) {
  737.      case 2: /* find state zone: CA, MD, NY, ...
  738.           * if there's no match then try the
  739.           * general string search.
  740.           */
  741.         if (!FindAbbrev(argv[i])) goto others;
  742.         break;
  743.  
  744.      case 3: /* find area code: 301, 718, ... */
  745.         if (isdigit(*argv[i]) && FindCode(argv[i]))
  746.             break;
  747.         /* otherwise try general search */
  748.  
  749.      default: /* state name: new*york, maryland, ... */
  750.      others:  /* or city name: Greenbelt, Fresno, ... */
  751.         if (!FindString(argv[i]))
  752.             printf("\nNot found, %s.\n", argv[i]);
  753.      } /* switch */
  754.     } /* for each argument */
  755.  
  756.     EXIT(0);
  757. }
  758.